package mainframe;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import shortcuthelper.ShortcutHelper;
import swingdisplay.EntriesTableModel;
import entry.Entry;

public class MainFrame extends JFrame {
	private static final long serialVersionUID = 1L;

	private JLabel abbreviationLabel;
	private JTextField abbreviationTextField;
	private JButton addButton;
	private JButton deleteButton;
	private JLabel descriptionLabel;
	private JTextArea descriptionTextArea;
	private JButton exportButton;
	private JLabel extensionLabel;
	private JTextField extensionTextField;
	private JButton importButton;
	private EntriesTableModel model;
	private ShortcutHelper sh;
	private JTable table;
	private JButton updateButton;
	private JButton editButton;
	private boolean editMode;
	private int currentlyEdited;
	

	public MainFrame(ShortcutHelper sh) {
		super("Abbr");
		this.sh = sh;
		editMode = false;
		setSize(800, 500);
		setLocation(200, 200);
		setMinimumSize(800, 500);
		initComponents();
		postInit();
		addListneres();
		organizeComponents();
		autoImport();
		setVisible(true);
		addItemMode();
	}

	private void addListneres() {
		addWindowListener(new WindowCloseAutoSaveListener());
		addButton.addActionListener(new AddButtonActionListener());
		deleteButton.addActionListener(new DeleteButtonActionListener());
		updateButton.addActionListener(new UpdateButtonActionListener());
		importButton.addActionListener(new ImportButtonActionListener());
		exportButton.addActionListener(new ExportButtonActionListener());
		editButton.addActionListener(new EditButtonActionListener());
		table.addMouseListener(new TableMouseListener());
	}

	private void autoExport() {
		File defExportFile = new File(System.getProperty("user.dir")
				+ System.getProperty("file.separator") + "abbr.xml");
		sh.exportList(defExportFile);
	}

	private void autoImport() {
		File defImportFile = new File(System.getProperty("user.dir")
				+ System.getProperty("file.separator") + "abbr.xml");
		if (!defImportFile.isFile()) {
			return;
		}
		sh.importList(defImportFile);
		model.setList(sh.getList());
		model.fireTableDataChanged();
	}

	private Entry harvestEntry() {
		if (abbreviationTextField.getText().isEmpty()
				|| extensionTextField.getText().isEmpty()) {
			return null;
		}
		Entry e = new Entry();
		e.setAbbr(abbreviationTextField.getText());
		e.setExtension(extensionTextField.getText());
		e.setDescription(descriptionTextArea.getText());
		return e;
	}

	private void initComponents() {
		abbreviationLabel = new JLabel("Abbreviation:");
		extensionLabel = new JLabel("Extension:");
		descriptionLabel = new JLabel("Description:");
		abbreviationTextField = new JTextField();
		extensionTextField = new JTextField();
		descriptionTextArea = new JTextArea();
		model = new EntriesTableModel();
		table = new JTable(model);
		addButton = new JButton("Add");
		deleteButton = new JButton("Delete");
		updateButton = new JButton("Update");
		importButton = new JButton("Import");
		exportButton = new JButton("Export");
		editButton = new JButton("Edit");
	}

	private void organizeComponents() {
		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		c.anchor = GridBagConstraints.NORTHWEST;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weighty = 0;
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 3;
		c.insets = new Insets(2, 2, 2, 2);
		add(abbreviationLabel, c);

		c.gridy++;
		add(abbreviationTextField, c);

		c.gridy++;
		add(extensionLabel, c);

		c.gridy++;
		add(extensionTextField, c);

		c.gridy++;
		add(descriptionLabel, c);

		c.fill = GridBagConstraints.BOTH;
		c.weighty = 1;
		c.gridy++;
		add(descriptionTextArea, c);

		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridwidth = 1;
		c.weighty = 0;
		c.gridy++;
		add(addButton, c);

		c.gridx++;
		add(deleteButton, c);

		c.gridx++;
		add(updateButton, c);

		c.gridy++;
		c.gridx = 0;
		add(importButton, c);

		c.gridx++;
		add(exportButton, c);
		
		c.gridx++;
		add(editButton, c);

		c.gridx++;
		add(new JLabel(), c);

		int gridHeightOfTable = c.gridy + 2;

		c.gridy = 0;
		c.gridx = 3;
		c.weightx = 1;
		c.weighty = 1;
		c.fill = GridBagConstraints.BOTH;
		c.gridheight = gridHeightOfTable;
		add(new JScrollPane(table), c);

	}

	private void postInit() {
		model.setList(sh.getList());
		table.getColumnModel().getColumn(0).setMaxWidth(100);
	}

	private void seedEntry(Entry entry) {
		if (entry == null) {
			entry = new Entry();
		}
		abbreviationTextField.setText(entry.getAbbr());
		extensionTextField.setText(entry.getExtension());
		descriptionTextArea.setText(entry.getDescription());
	}

	private void setMinimumSize(int i, int j) {
		setMinimumSize(new Dimension(i, j));
	}
	
	private void setEditingBackground() {
		abbreviationTextField.setBackground(Color.LIGHT_GRAY);
		extensionTextField.setBackground(Color.LIGHT_GRAY);
		descriptionTextArea.setBackground(Color.LIGHT_GRAY);
	}
	
	private void disableTextAreas() {
		abbreviationTextField.setEditable(false);
		extensionTextField.setEditable(false);
		descriptionTextArea.setEditable(false);
	}
	
	private void enableTextAreas() {
		abbreviationTextField.setEditable(true);
		extensionTextField.setEditable(true);
		descriptionTextArea.setEditable(true);
	}
	
	private void clearTextAreas() {
		abbreviationTextField.setText(null);
		extensionTextField.setText(null);
		descriptionTextArea.setText(null);
	}
	
	private void setDefaultBackground() {
		abbreviationTextField.setBackground(Color.WHITE);
		extensionTextField.setBackground(Color.WHITE);
		descriptionTextArea.setBackground(Color.WHITE);
	}
	
	private void readOnlyMode() {
		editMode = false;
		setDefaultBackground();
		disableTextAreas();
		updateButton.setEnabled(false);
		editButton.setEnabled(true);
		deleteButton.setEnabled(true);
		addButton.setEnabled(true);
		addButton.setText("New");
	}
	
	private void enableEditingMode() {
		editMode = true;
		currentlyEdited = table.getSelectedRow();
		setEditingBackground();
		enableTextAreas();
		updateButton.setEnabled(true);
		editButton.setEnabled(false);
		deleteButton.setEnabled(true);
		addButton.setEnabled(false);
	}
	
	private void addItemMode() {
		setDefaultBackground();
		enableTextAreas();
		clearTextAreas();
		addButton.setEnabled(true);
		addButton.setText("Add");
		updateButton.setEnabled(false);
		editButton.setEnabled(false);
		deleteButton.setEnabled(false);
	}

	class AddButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if(addButton.getText().equals("Add")) {
				Entry entry = harvestEntry();
				addItemMode();
				if (entry != null) {
					sh.getList().add(entry);
					Collections.sort(sh.getList());
					model.fireTableDataChanged();
				}
			}
			else {
				addItemMode();
			}
		}
	}

	class DeleteButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			addItemMode();
			if (table.getSelectedRow() > -1) {
				sh.getList().remove(table.getSelectedRow());
				model.fireTableDataChanged();
				seedEntry(null);
			}
		}
	}

	class ExportButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser chooser = new JFileChooser(
					System.getProperty("user.dir"));
			chooser.setFileFilter(new XmlFileFilter());
			int response = chooser.showSaveDialog(MainFrame.this);
			if (response == JFileChooser.APPROVE_OPTION) {
				sh.exportList(chooser.getSelectedFile());
			}
		}
	}
	
	class EditButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			enableEditingMode();
		}
	}


	class ImportButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser chooser = new JFileChooser(
					System.getProperty("user.dir"));
			chooser.setFileFilter(new XmlFileFilter());
			int response = chooser.showOpenDialog(MainFrame.this);
			if (response == JFileChooser.APPROVE_OPTION) {
				importList(chooser.getSelectedFile());
			}
		}

		private void importList(File source) {
			sh.importList(source);
			model.setList(sh.getList());
			Collections.sort(sh.getList());
			model.fireTableDataChanged();
		}
	}
	
	class UpdateButtonActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			readOnlyMode();
			editButton.setEnabled(false);
			if (table.getSelectedRow() > -1) {
				Entry entry = harvestEntry();
				if (entry != null) {
					updateEntry();
				}
			}
		}

	
	}
	
	private void updateEntry() {
		sh.getList().set(currentlyEdited, harvestEntry());
		Collections.sort(sh.getList());
		model.fireTableDataChanged();
	}

	class TableMouseListener extends MouseAdapter {

		@Override
		public void mouseClicked(MouseEvent e) {
			if (editMode) {
				if (JOptionPane.showConfirmDialog(null, "Save changes?",
				"WARNING", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
				if (table.getSelectedRow() > -1) {
				Entry entry = harvestEntry();
				if (entry != null) {
				updateEntry();
				}
				}
				}
				}
				setDefaultBackground();
				editButton.setEnabled(true);
				updateButton.setEnabled(false);
			
			readOnlyMode();
			if (table.getSelectedRow() > -1) {
				seedEntry(sh.getList().get(table.getSelectedRow()));
			}
		}
	}

	class WindowCloseAutoSaveListener extends WindowAdapter {

		@Override
		public void windowClosing(WindowEvent arg0) {
			autoExport();
			System.exit(0);
		}
	}
}
